package com.cskaoyan.javse.oop3._1interface._1basic;

/**
 * @description: 接口的特点
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 接口的声明/定义特点:
 *      接口定义语法:
 *      [访问权限修饰符] interface 接口名{
 *      }
 *      接口是抽象的,它默认就被声明为abstract,没有必要在加上abstract修饰
 *      显然它是不能和final共存的
 *
 *     接口的实现类,很多程序员喜欢在接口的包中创建一个新的包叫impl,然后创建接口的实现类,叫接口名+Impl
 *
 * 接口的成员特点:
 *      1.成员变量
 *          在接口中,是可以定义成员变量的,但是接口中的成员变量默认是public static final修饰的公共的全局常量
 *          细节:
 *              a.public是不可更改的,不能用别的修饰符
 *              b.public static final都是隐含的,不要写出来
 *              c.接口中的全局常量必须显式赋值,不能用静态代码块赋值,因为接口没有静态代码块
 *              d.接口侧重于行为,功能的扩展,绝大多数接口中都是没有全局常量的,都只有方法
 *
 *      2.抽象方法/成员方法:
 *          接口中可以定义抽象方法,实际上接口中的方法在Java8之前只能是抽象方法,默认使用public abstract修饰,这两个关键字可以不用写出来
 *          接口表示对功能的扩展,常见的接口书写都是只有光秃秃的抽象方法
 *          接口的普通实现类必须实现接口的全部抽象方法
 *          接口中的抽象方法仍然是起着占位的作用
 *
 *          Java8中接口的语法迎来了大的变动,新增了两种具有方法体的实现方法:
 *              1.默认方法
 *                  默认方法的语法:
 *                  default 返回值类型 方法名(形参列表){
 *                      //方法体
 *                  }
 *                  接口中的默认方法的访问权限修饰符是public,不可更改
 *                  默认方法的作用:
 *                      抽象类中的实现方法是用来作为子类的默认实现,但是接口不具备这个功能
 *                      接口表示对功能的扩展,它更多的是一种标准和规范,多数情况下它不需要实现方法
 *                      即便这样java8仍然新增了默认方法,主要是两个角度考虑:
 *                          a.接口中一旦有了默认方法,接口的灵活性增加了,之前全部都是抽象方法时,接口中一旦新增任何方法,子类都必须实现它,而现在有了默认方法,就不需要这么做--> 需要实现的就自己重写,不需要的就直接继承.代码的兼容性和灵活性就增加了
 *                          b.默认方法配合Stream API使用,可以完成函数式编程(留个印象就行了)
 *                      除此之外,接口中的默认方法,可以配合接口的"多实现",实现真正意义上的多继承
 *                      多继承在java中是不允许,默认方法设计的目的也不是为了多继承,不要在开发中用默认方法实现多继承.并且实际上我们不会在开发中在接口中写默认方法
 *
 *              2.静态方法
 *                  静态方法:
 *                  static 返回值类型 方法名(形参列表){
 *                      //方法体
 *                  }
 *                  注意:
 *                  1.接口中的静态方法也是默认public修饰的,不可更改
 *                  2.它的调用是用接口名.静态方法名
 *                  3.接口中的静态方法不能被子类继承,不能使用实现类类名点去调用
 *                  4.接口中的静态方法也是为了配合Stream API使用的,正常开发不要轻易在接口中写静态方法
 *                  5.接口自从java8以后有了静态方法,甚至可以写一个main方法(了解)
 *
 *      综上,接口中虽然可以写具体实现方法,但是还是尽量不要写,除非有特别的需求.接口就是对功能的扩展,就是规范,就是约束
 *          它里面应该仅有抽象方法
 *          在开发中,做基础业务的程序员,叫做"写接口,开发接口"的人
 *
 *      4.构造方法
 *          接口和抽象类都不能创建对象,但是抽象类中有普通成员变量需要赋值,但是接口中没有
 *          所以接口是没有构造方法
 *
 *          两个问题:
 *              1.实现接口的类,如果没有明确继承一个其他类,那么子类对象的隐式初始化super()指向Object类
 *              2.接口有没有继承Object?
 *                  接口虽然不是类,但是它也继承了Object类
 *
 *      5.代码块
 *          没有静态代码块,也没有构造代码块
 *
 * 接口的子类特点:
 *      接口的子类可以是什么?
 *      1.普通类,普通类实现接口,必须实现所有的抽象方法
 *      2.抽象类,抽象类实现接口,不需要实现抽象方法
 *      3.接口,接口可以继承一个接口,也是不需要实现抽象方法的
 *
 * 总结一下,接口和类的继承/实现的规则:
 *      1.继承(extends)是不能跨越种族的,类和类继承,接口和接口继承,接口和类之间没有继承关系
 *          普通类继承一个抽象类,需要实现里面的所有抽象方法
 *          抽象类继承一个抽象类,不需要实现里面的抽象方法
 *          抽象类继承一个普通类,也是可以的
 *          接口在继承一个接口后,会得到接口的所有抽象方法,但是也不需要实现
 *          类的继承是单继承的,接口的继承是多继承的
 *      2.实现(implements),必须发现在类与接口之间,接口和类是没有任何关系
 *          普通类实现接口,必须实现所有抽象方法
 *          抽象类实现接口,不需要实现抽象方法
 *          
 */
//Modifier 'abstract' is redundant for interfaces
public interface ITest {
    /*public static void main(String[] args) {
        System.out.println("hello world!");
    }*/
    //定义成员变量
    //Variable 'a' might not have been initialized
    //int a;
    //static int b;
    //public static final int C = 10;
    /*static {
    }*/

    //以后接口中定义全局常量,这么写即可
    int A = 10;

    //定义抽象方法
    //public abstract void test();

    //接口中定义抽象方法,这么去写
    void test();

    int test(int a);

    String add(String s);

    //定义Java8中新增的默认方法
    default void testDefault() {
        System.out.println("ITest1");
    }

    //定义Java8中新增的静态方法
    static void testStatic() {
        System.out.println("static");
    }

}
